<template>
  <div class="usinghelp-container">
    <div class="btn">
      <el-button circle @click="handleEnlarge">
        <el-icon> <elementPlus /> </el-icon
      ></el-button>
      <el-button circle @click="handleScale">
        <el-icon> <elementMinus /> </el-icon
      ></el-button>
    </div>
    <div class="pdf-view">
      <canvas
        :id="`pdfCanvas${page}`"
        v-for="page in state.pdfPages"
        :key="page"
      ></canvas>
    </div>
  </div>
</template>

<script lang="ts" setup name="usinghelp">
import { reactive, onMounted, nextTick, watch } from "vue";
import request from "/@/utils/request";
import * as PDF from "pdfjs-dist";
import workerSrc from "pdfjs-dist/build/pdf.worker.entry.js"; // 引入时如果报红线错误，不影响运行， 或在index.d.ts中声明declare
const props = defineProps({
  pdfPath: {
    type: String,
  },
  pdfId: { type: String },
});
const state = reactive<any>({
  pdfPath: "", //本地PDF文件路径放在/public中
  pdfPages: "", // 页数
  pdfWidth: "", // 宽度
  pdfSrc: "", // 地址
  pdfScale: 1.0, // 放大倍数
  scaleNum: 60,
  pdfId: "",
});
// 此处为正确写法---原来我的参数用的响应式写法，就会报错Cannot read from private field
let pdfDoc: any = ""; // 文档内容---必须使用非响应式存储
let canvas: any;
// 页面加载时
onMounted(() => {
  initTableData();
});

// 获取文件流
const getFile = () => {
  request({
    url: "/api/system/annex/downFile?fileId=" + state.pdfId,
    method: "post",
    responseType: "blob",
  }).then((res) => {
    let blob = new Blob([res], { type: "application/pdf" });
    let url = window.URL.createObjectURL(blob);
    PDF.GlobalWorkerOptions.workerSrc = workerSrc;
    loadFile(url);
  });
};

// 初始化表格数据
const initTableData = () => {
  PDF.GlobalWorkerOptions.workerSrc = workerSrc;
  loadFile(state.pdfPath);
};

// s
const loadFile = (url: string) => {
  let loadingTask = PDF.getDocument({
    url: url,
    cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.10.377/cmaps/",
    cMapPacked: true,
    enableXfa: true,
  });
  loadingTask.promise.then((pdf: any) => {
    pdfDoc = pdf;
    state.pdfPages = pdf.numPages;
    nextTick(() => {
      renderPage(1); // 表示渲染第 1 页
    });
  });
};

// 渲染指定页面的内容
const renderPage = (num: number) => {
  pdfDoc.getPage(num).then((page: any) => {
    canvas = document.getElementById(`pdfCanvas${num}`);
    let ctx = canvas.getContext("2d");
    let dpr = window.devicePixelRatio || 1;
    let bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      0.4;
    let ratio = dpr / bsr;
    let viewport = page.getViewport({ scale: state.pdfScale });
    canvas.width = viewport.width * ratio;
    canvas.height = viewport.height * ratio;
    // canvas.style.width = viewport.width + "px";
    // canvas.style.height = viewport.height + "px";
    canvas.style.width = "60%";
    // canvas.style.height = "100%";
    state.pdfWidth = viewport.width + "px";
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    // 将 PDF 页面渲染到 canvas 上下文中
    let renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    page.render(renderContext);
    if (state.pdfPages > num) {
      renderPage(num + 1);
    }
  });
};

// 缩放
const handleScale = () => {
  state.scaleNum = state.scaleNum - 5;
  for (let index = 1; index <= state.pdfPages; index++) {
    let scale = document.getElementById(`pdfCanvas${index}`);
    scale.style.width = state.scaleNum + "%";
  }
};
// 放大
const handleEnlarge = () => {
  state.scaleNum = state.scaleNum + 5;
  for (let index = 1; index <= state.pdfPages; index++) {
    let scale = document.getElementById(`pdfCanvas${index}`);
    scale.style.width = state.scaleNum + "%";
  }
};
watch(
  () => props.pdfPath,
  () => {
    if (props.pdfPath) {
      state.pdfPath = props.pdfPath;
      initTableData();
    }
  }
);
watch(
  () => props.pdfId,
  () => {
    if (props.pdfId) {
      state.pdfId = props.pdfId;
      getFile();
    }
  }
);
</script>

<style lang="scss" scoped>
.usinghelp-container {
  .pdf-view {
    height: 77vh;
    margin: 0 auto;
    border: 1px solid #d9d9d9;
    overflow: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .btn {
    position: absolute;
    right: 30px;
    top: 90px;
  }
}
</style>
